#include "user_speech_recognition.h"
#include "drv_audio.h"
#include "app_timer_process.h"
#include "algo_asr_vad.h"
#include "flash_data.h"
#include "flash_melcep.h"
#include "algo_asr_dtw.h"
#include "bluetooth_link.h"
#include "nrf_delay.h"

#define WRITE_FLASH_LEN    1024

static uint8_t m_speech_recognition_status;
static bool mel_cep_over_flag       = false;
static int16_t m_start_point,m_end_point;
float mel_cep_write_flash[WRITE_FLASH_LEN] = {0.0f};   // 960个melcep值，最后8个byte存储alg_asr_melcep结构体
static uint8_t m_user_asr_index = 0;
float dtw_distence[5] = {0.0f};

// 一个待识别的语音，一个唤醒语音库，四个语音库语音
alg_asr_melcep m_alg_asr_melcep[FLASH_MELCEP_BLOCK_NUM];

/**@brief Function for caculatting mel cep.
 */
void mel_cep_event_process(void *p_contex)
{
    uint8_t is_melcep_finish = 0;
    uint32_t * p;
    static uint8_t l;
    uint32_t audio_start_add;
    int16_t *p_audio_add;
    float Mindistence = 3.4e38;
    uint8_t min_distence_index = 100;

    audio_start_add = flash_data_get_startADD();
    p_audio_add     = (int16_t*)audio_start_add;
    //if(flash_write_flag)
    if(1)
    {
        ////flash_write_flag = false;
        // if current mode is MODE_AUDIO_RECOGNITION, we should enter dtw algorithm to 
        // caculate the distence after caculating the mel_cep. In other case, we should 
        // only caculate mel_cep and storage it to inner flash.
        if(MODE_AUDIO_RECOGNITION == m_speech_recognition_status)
        {
            is_melcep_finish = Melcep(p_audio_add,m_start_point,m_end_point,mel_cep_write_flash);
            Meldtw(m_alg_asr_melcep,dtw_distence,FLASH_MELCEP_BLOCK_NUM);
            for(uint8_t i = 0;i < 5;i++)
            {
                if(dtw_distence[i] < Mindistence)
                {
                    Mindistence = dtw_distence[i];
                    min_distence_index = i;
                }
            }
            if(Mindistence < 15000)
            {
                NRF_UART_TRANSMIT("ASR RET %d OK\n",min_distence_index);
            }
            else
            {
                NRF_UART_TRANSMIT("ASR RET %d OK\n",9);
            }
        }
        // 其它情况，只可能是语音库训练指令模式
        else
        {
            if(mel_cep_over_flag)
            {
                mel_cep_over_flag = false;
                //app_timer_stop(m_wr_flash_delay_timer_id);
                //Display_show_input_voice_success();
            }
            else
            {
////                m_mel_cep.flash_write = m_speech_recognition_status + 1;
////                m_mel_cep.len[m_speech_recognition_status - 1] = EndPoint - StartPoint + 1;
                is_melcep_finish = Melcep(p_audio_add,m_start_point,m_end_point,mel_cep_write_flash);
                scan_stop();
                flash_melcep_store(m_user_asr_index,(uint8_t *)mel_cep_write_flash,sizeof(mel_cep_write_flash),0);
                if(m_user_asr_index == 1)
                {
                    NRF_UART_TRANSMIT("Weak Up OK\n");
                }
                else if(m_user_asr_index == 2)
                {
                    NRF_UART_TRANSMIT("Open Curtain OK\n");
                }
                else if(m_user_asr_index == 3)
                {
                    NRF_UART_TRANSMIT("Close Curtain OK\n");
                }
                else if(m_user_asr_index == 4)
                {
                    NRF_UART_TRANSMIT("Open Light OK\n");
                }
                else if(m_user_asr_index == 5)
                {
                    NRF_UART_TRANSMIT("Close Light OK\n");
                }
////                scan_start();
                //NRF_LOG_PRINTF("\nO_Write Succeful!!");
            }
        }
    }
}

void mel_cep_event_handler(void)
{
    uint32_t audio_start_add;
    int16_t *p_audio_add;
    uint32_t mel_cep_add;
    uint32_t *p_melcep_add;

    audio_start_add = flash_data_get_startADD();
    p_audio_add     = (int16_t*)audio_start_add;
    mel_cep_add     = flash_melcep_get_startADD();
    p_melcep_add    = (uint32_t *)mel_cep_add;
    // 进行端点检测
    alg_asr_vad(8000, p_audio_add, FLASH_DATA_BLOCK_SIZE * CONFIG_AUDIO_FRAME_TIMES / 2, &m_start_point,&m_end_point);
    if(m_start_point <= 2)
    {
        m_start_point = 2;
    }
    if(m_end_point < m_start_point)
    {
        m_end_point = 38;
    }
    algo_dtw_set_audio_point(m_start_point - 2);
    // 语音识别的melcep参数不存储flash，用mel_cep_write_flash RAM中的数据即可
    if(m_user_asr_index == 0)
    {
        m_alg_asr_melcep[m_user_asr_index].melcep_len = m_end_point - m_start_point + 1;
        m_alg_asr_melcep[m_user_asr_index].melcep_add = (uint32_t *)mel_cep_write_flash;
        memcpy(&mel_cep_write_flash[WRITE_FLASH_LEN - 2],&m_alg_asr_melcep[m_user_asr_index],sizeof(alg_asr_melcep));
    }
    // 语音库melcep参数需要存储flash，地址为melcep的存储地址
    else
    {
        m_alg_asr_melcep[m_user_asr_index].melcep_len = m_end_point - m_start_point + 1;
        m_alg_asr_melcep[m_user_asr_index].melcep_add = (uint32_t *)(mel_cep_add + (m_user_asr_index * FLASH_MELCEP_BLOCK_SIZE));
        memcpy(&mel_cep_write_flash[WRITE_FLASH_LEN - 2],&m_alg_asr_melcep[m_user_asr_index],sizeof(alg_asr_melcep));
    }
    NRF_UART_TRANSMIT("start:%d,end:%d\r\n",m_start_point,m_end_point);

    // 开启定时器，计算melcep,计算耗时较长，放在定时器中，分时间段计算
    app_start_timer(APP_TIMER_MELCEP);
}

// pdm数据flash区域擦除完成后，再对mepcep数据区域进行擦除
void pdm_flash_finish_handler(uint8_t num)
{
    // 用于存储melceps数据
    flash_melcep_clear(m_user_asr_index,1);
}

// melcep数据flash区域擦除完成后，startPDM，进行语音采集
void melcep_flash_finish_handler(uint8_t num)
{
    start_pdm_process_after_flash();;
}

static void alg_asr_melcep_init(alg_asr_melcep *melcep, uint32_t len)
{
    uint32_t add;
    uint32_t *p_add;
    uint32_t i = 0;

    add     = flash_melcep_get_startADD();
    for(i = 0;i < len; i++)
    {
        p_add = (uint32_t *)(add + i * FLASH_MELCEP_BLOCK_SIZE);
        memcpy(&melcep[i],&p_add[WRITE_FLASH_LEN - 2],sizeof(alg_asr_melcep));
    }
}

/**@brief Function to Init speech recognition algorithm
* total API to init this algorithm
*/
void user_speech_recogniton_init(void)
{
    // pdm数据采集完毕后，计算mel系统，进行语音识别等操作
    drv_audio_pdm_finished_reg(mel_cep_event_handler);
    // pdm数据flash区域擦除完成
    flash_data_pdm_eraser_finish_reg(pdm_flash_finish_handler);
    // mel数据flash区域擦除完成
    flash_melcep_eraser_finish_reg(melcep_flash_finish_handler);
    app_create_timer(APP_TIMER_MELCEP);
    alg_asr_melcep_init(m_alg_asr_melcep,FLASH_MELCEP_BLOCK_NUM);
}


// 语音识别
int8_t user_algo_asr_start(uint8_t num)
{
    m_speech_recognition_status = num;
    // m_user_asr_index需要重新整理， 整理后0代表待识别的语音
    m_user_asr_index = num;
    start_pcm_data(num);
    return 0;
}

// 语音训练
int8_t user_algo_asr_trainning_start(uint8_t num)
{
    m_speech_recognition_status = num;
    m_user_asr_index = num;
    start_pcm_data(num);
    return 0;
}

void print_audio_raw(void)
{
    uint32_t audio_start_add;
    int16_t *p_audio_add;
    uint32_t len = 0;

    audio_start_add = flash_data_get_startADD();
    p_audio_add     = (int16_t*)audio_start_add;
    NRF_UART_TRANSMIT("start:%d,end:%d\r\n",m_start_point*240,m_end_point*240);
    //len = CONFIG_AUDIO_FRAME_SIZE_SAMPLES / 2 * CONFIG_AUDIO_FRAME_TIMES;
    NRF_UART_TRANSMIT("data:\n");
    start_print_audio_data();
    /*
    for(uint32_t i = 0; i < len; i++)
    {
        NRF_UART_TRANSMIT("%d\n",p_audio_add[i]);
        nrf_delay_ms(1);
    }
    */
}

